package com.topwalk.datacollect.controller;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.topwalk.datacollect.config.ApplicationConfig;
import com.topwalk.datacollect.config.HeaderConfig;
import com.topwalk.datacollect.constant.APIConstant;
import com.topwalk.datacollect.util.DateUtil;
import com.topwalk.datacollect.util.KeyFactory;
import com.topwalk.datacollect.util.SocketCP;

@RestController
@RequestMapping("/collectsvc")
public class SyncController {

	private static final Logger LOG = LoggerFactory.getLogger(SyncController.class);

	/**
	 * 平台注册信息
	 * @param data
	 * @return
	 */
	@PostMapping(value={"PlatInf","InnerLinkInf","OuterLinkInf","BizInf","BizProInf","DeviceInf"})
	public String sync(String data, HttpServletRequest request) {

		// 获取请求接口
		StringBuffer url = request.getRequestURL();
        int index = url.lastIndexOf("/");
        String api = url.substring(index + 1);
        LOG.info("接收restful："+api);
        // 获取发送响应信息
		String[] apiInfo = APIConstant.API_TAB_SYNC.get(api);
		String tableName = apiInfo[0];
		// 设置响应内容
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		String ok_msg = "";
		String ng_msg = "{\"desc\":\"数据采集失败\",\"status\":\"001\"}";

		// json字符串转map列表
		List<Map<String, Object>> dataList = null;
		ObjectMapper mapper = new ObjectMapper();
		try {
			dataList = mapper.readValue(data,new TypeReference<List<Map<String, Object>>>(){});
		} catch (Exception e) {
			e.printStackTrace();
			return ng_msg;
		}

		String ip = ApplicationConfig.SYNC_SOCKET_IP;
		int port = ApplicationConfig.SYNC_SOCKET_PORT;
		// 获取socket连接
		LinkedBlockingQueue<Socket> socketCP = SocketCP.SOCKET_QUEUE.get(ip+"_"+port);
		Socket socket = null;
		DataOutputStream dos = null;
		try {
			socket = socketCP.take();// 若获取不到socket，将阻塞
			LOG.info("socketCP.get");
		} catch (Exception e) {
			e.printStackTrace();
			return ng_msg;
		}
		try {
			dos = new DataOutputStream(socket.getOutputStream());
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 发送数据
		Encoder encoder = Base64.getEncoder();
		String header = new String(HeaderConfig.SYNC);
		header = header.replace("$dataType", tableName);
		header = header.replace("$logTime", DateUtil.getCurrentTime("yyyyMMddHHmmss"));
		header = header.replace("$batchNum", KeyFactory.newUUID());
		header = header.replace("$totalCount", String.valueOf(dataList.size()));
		int errCount = 0;
		if(dataList.size() == 0){
			Map<String, Object> rowResult = new HashMap<String, Object>();
			boolean success = true;
			try {
				// json转base64
				String base64 = encoder.encodeToString("{}".getBytes("UTF-8"));
				// 添加businessData
				String str = header.replace("$businessData", base64);
				// 发送数据
				dos.write((str+"\n").getBytes("UTF-8"));
		        LOG.info("发送flume："+str);
			} catch (IOException e) {
				success = false;
				LOG.error("发送数据失败，socket连接异常！", e);
			} catch (Exception e) {
				success = false;
				LOG.error("发送数据失败！", e);
			}
			if(success){
				rowResult.put("desc", "数据采集成功");
				rowResult.put("status", "000");
			}else{
				rowResult.put("desc", "数据采集失败");
				rowResult.put("status", "001");
			}
			result.add(rowResult);
		}else{
			for(int i=0; i<dataList.size(); i++){
				Map<String, Object> rowResult = new HashMap<String, Object>();
				boolean success = true;
				try {
					Map<String, Object> map = dataList.get(i);
					// 获取id信息
					for(int j=1; j<apiInfo.length; j++){
						rowResult.put(apiInfo[j], map.get(apiInfo[j]));
					}
					// map转json
					String json = mapper.writeValueAsString(map);
					// json转base64
					String base64 = encoder.encodeToString(json.getBytes("UTF-8"));
					// 添加businessData
					String str = header.replace("$businessData", base64);
					// 发送数据
					dos.write((str+"\n").getBytes("UTF-8"));
					LOG.info("发送flume："+str);
				} catch (IOException e) {
					success = false;
					errCount++;
					LOG.error("发送数据失败，socket连接异常！", e.getMessage());
				} catch (Exception e) {
					success = false;
					errCount++;
					LOG.error("发送数据失败！", e.getMessage());
				}
				if(success){
					rowResult.put("desc", "数据采集成功");
					rowResult.put("status", "000");
				}else{
					rowResult.put("desc", "数据采集失败");
					rowResult.put("status", "001");
				}
				result.add(rowResult);
			}
		}
		try {
			if(errCount > 0){
				// 认为socket失效，重新建立socket连接
				socket.close();
				socket = new Socket(ip, port);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 将连接放回队列
		try {
			socketCP.put(socket);
			LOG.info("socketCP.put");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		// 设置响应结果
		try {
			ok_msg = mapper.writeValueAsString(result);
		} catch (JsonProcessingException e) {
			ok_msg = ng_msg;
			e.printStackTrace();
		}
		
		return ok_msg;
	}

}
